﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using WooCoo.ObjectModel.ManagedProperty.PropertyDescriptors;

namespace WooCoo.ObjectModel.ManagedProperty
{
    [Serializable]
    public abstract partial class ManagedPropertyBase : IManagedProperty, INotifyPropertyChanged, ICustomTypeDescriptor
    {
        private FieldDataManager _fieldDataManager;

        [NonSerialized]
        private PropertyInfoSet _properties;

        internal FieldDataManager FieldDataManager
        {
            get
            {
                return _fieldDataManager;
            }
        }

        /// <summary>
        /// 从属性缓存仓库中取得托管属性集，还将包括基类属性
        /// </summary>
        internal PropertyInfoSet Properties
        {
            get
            {
                if (this._properties == null)
                    this._properties = PropertyInfoRepository.Instance.GetPropertyInfoSet(this.GetType());
                return this._properties;
            }
        }

        public ManagedPropertyBase()
        {
            _fieldDataManager = new FieldDataManager(this);
        }

        #region GetProperty
        public virtual object GetProperty(IPropertyInfo property)
        {
            return this._fieldDataManager.GetProperty(property);
        }

        public virtual T GetProperty<T>(PropertyInfo<T> property)
        {
            return this._fieldDataManager.GetProperty<T>(property);
        }
        #endregion

        #region SetProperty
        /// <summary>
        /// 设置属性值,如果属性发生变更，则触发PropertyChanged事件
        /// </summary>
        /// <param name="property"></param>
        /// <param name="value"></param>
        public virtual void SetProperty(IPropertyInfo property, object value)
        {
            if (this._fieldDataManager.SetProperty(property, value))
                this.OnPropertyChanged(property.Name);
        }

        /// <summary>
        /// 设置属性值，如果属性发生变更，则触发PropertyChanged事件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="property"></param>
        /// <param name="value"></param>
        public virtual void SetProperty<T>(PropertyInfo<T> property, T value)
        {
            if (this._fieldDataManager.SetProperty(property, value))
                this.OnPropertyChanged(property.Name);
        }

        #endregion

        #region LoadProperty
        /// <summary>
        /// 为属性加载值，不触发PropertyChanged事件
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <param name="property"></param>
        /// <param name="value"></param>
        /// <remarks>Load方式不进行任何值验证，也不触发PropertyChanged事件</remarks>
        public virtual void LoadProperty<T>(PropertyInfo<T> property, T value)
        {
            this._fieldDataManager.LoadProperty(property, value);
        }

        /// <summary>
        /// 为属性加载值，不触发PropertyChanged事件
        /// </summary>
        /// <param name="property"></param>
        /// <param name="value"></param>
        public virtual void LoadProperty(IPropertyInfo property, object value)
        {
            this._fieldDataManager.LoadProperty(property, value);
        }
        #endregion

        public IPropertyInfo FindProperty(string propertyName)
        {
            if (string.IsNullOrWhiteSpace(propertyName)) throw new ArgumentNullException("managedProperty");

            return this._properties.GetProperties().FirstOrDefault(p => p.Name == propertyName);
        }
        /// <summary>
        /// 根据托管属性名读取本对象的值。
        /// </summary>
        /// <param name="propertyName"></param>
        /// <param name="value"></param>
        /// <returns>如果没有这个托管属性还没有加载到对象中，或者这个没有这个托管属性。则返回false。
        /// 如果返回真，表示设置成功。</returns>
        public bool TryGetPropertyValue(string propertyName, out object value)
        {
            value = null;

            var property = this.FindProperty(propertyName);
            if (property != null)
            {
                value = this.GetProperty(property);
                return true;
            }

            return false;
        }

        #region PropertyChanged

        /// <summary>
        /// 属性变更事情全部在客户端操作，不做序列化操作。
        /// </summary>
        [NonSerialized]
        private PropertyChangedEventHandler _propertyChangedHandlers;

        public event PropertyChangedEventHandler PropertyChanged
        {
            add
            {
                _propertyChangedHandlers = (PropertyChangedEventHandler)
                  System.Delegate.Combine(_propertyChangedHandlers, value);
            }
            remove
            {
                _propertyChangedHandlers = (PropertyChangedEventHandler)
                  System.Delegate.Remove(_propertyChangedHandlers, value);
            }
        }

        /// <summary>
        /// 当属性发生变更时触发PropertyChanged事件
        /// </summary>
        /// <param name="propertyName"></param>
        protected virtual void OnPropertyChanged(string propertyName)
        {
            if (this._propertyChangedHandlers != null)
                this._propertyChangedHandlers(this, new PropertyChangedEventArgs(propertyName));
        }
        #endregion

        #region ICustomTypeDescriptor Members

        PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties(Attribute[] attributes)
        {
            return PropertyDescriptorFactory.GetProperties(this);
        }

        //以下实现复制自 DataRowView

        AttributeCollection ICustomTypeDescriptor.GetAttributes()
        {
            return new AttributeCollection(null);
        }
        string ICustomTypeDescriptor.GetClassName()
        {
            return null;
        }
        string ICustomTypeDescriptor.GetComponentName()
        {
            return null;
        }
        TypeConverter ICustomTypeDescriptor.GetConverter()
        {
            return null;
        }
        EventDescriptor ICustomTypeDescriptor.GetDefaultEvent()
        {
            return null;
        }
        PropertyDescriptor ICustomTypeDescriptor.GetDefaultProperty()
        {
            return null;
        }
        object ICustomTypeDescriptor.GetEditor(Type editorBaseType)
        {
            return null;
        }
        EventDescriptorCollection ICustomTypeDescriptor.GetEvents()
        {
            return new EventDescriptorCollection(null);
        }
        EventDescriptorCollection ICustomTypeDescriptor.GetEvents(Attribute[] attributes)
        {
            return new EventDescriptorCollection(null);
        }
        PropertyDescriptorCollection ICustomTypeDescriptor.GetProperties()
        {
            return ((ICustomTypeDescriptor)this).GetProperties(null);
        }
        object ICustomTypeDescriptor.GetPropertyOwner(PropertyDescriptor pd)
        {
            return this;
        }
        /// <summary>
        /// 重设置为默认值，为ICustomerDescription接口需要方法
        /// </summary>
        /// <param name="propertyInfo"></param>
        internal void ResetProperty(IPropertyInfo propertyInfo)
        {
            this.SetProperty(propertyInfo, null);
        }
        #endregion

        public IEnumerable<IFieldData> GetDirtyFieldDatas()
        {
            return this._fieldDataManager.GetDirtyFieldDatas();
        }

    }
}
